package com.antd.admin.server.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.antd.admin.api.entity.SysDept;
import com.antd.admin.api.entity.SysUser;
import com.antd.admin.api.vo.SysDeptTreeVo;
import com.antd.admin.server.mapper.SysDeptMapper;
import com.antd.admin.server.service.ISysDeptService;
import com.antd.admin.server.service.ISysUserService;
import com.antd.common.auth.util.AntdSecurityUtil;
import com.antd.common.core.constant.Constant;
import com.antd.common.core.exception.BaseException;
import com.antd.common.core.util.AntdDeptUtil;
import com.antd.common.core.util.AntdMenuUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 部门管理 服务实现类
 * </p>
 *
 * @author 子丶沫
 * @since 2020-11-18
 */
@Service
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> implements ISysDeptService {

    @Autowired
    private ISysUserService userService;
    @Override
    public List<String> queryDeptIds(String deptId) {
        SysDept department = this.getDepartment(deptId);
        List<String> deptIdList = new ArrayList<>();
        if(ObjectUtil.isNotNull(department)){
            deptIdList.add(department.getDeptId());
            addDeptIdList(deptIdList,department);
        }
        return deptIdList;
    }

    @Override
    public List<SysDeptTreeVo> getDeptTree() {
        List<SysDept> deptList = baseMapper.selectList(Wrappers
                .<SysDept>lambdaQuery()
                .select(SysDept::getDeptId,
                        SysDept::getName,
                        SysDept::getParentId,
                        SysDept::getSort,
                        SysDept::getRemark,
                        SysDept::getCreateTime,
                        SysDept::getStatus));
        List<SysDeptTreeVo> deptTreeVoList = deptList.stream()
                .filter(sysDept -> Constant.PARENT_ID.equals(sysDept.getParentId()) || ObjectUtil.isNull(sysDept.getParentId()))
                .peek(sysDept -> sysDept.setLevel(0))
                .map(dept -> {
                    SysDeptTreeVo deptTreeVo = new SysDeptTreeVo();
                    BeanUtil.copyProperties(dept, deptTreeVo);
                    deptTreeVo.setTitle(dept.getName());
                    deptTreeVo.setParentName("一级部门");
                    deptTreeVo.setKey(dept.getDeptId());
                    deptTreeVo.setLabel(dept.getName());
                    deptTreeVo.setValue(dept.getDeptId());
                    return deptTreeVo;
                }).collect(Collectors.toList());
        AntdDeptUtil.findDeptTreeChildren(deptTreeVoList,deptList);
        return deptTreeVoList;
    }

    @Override
    public List<SysDeptTreeVo> searchDept(String searchText) {
        List<SysDept> deptList = this.list(Wrappers.<SysDept>query()
                .select()
                .lambda()
                .like(StrUtil.isNotEmpty(searchText), SysDept::getName, searchText));
        return deptList.stream()
                .map(dept->{
                    SysDeptTreeVo deptTreeVo=new SysDeptTreeVo();
                    BeanUtils.copyProperties(dept,deptTreeVo);
                    deptTreeVo.setTitle(dept.getName());
                    deptTreeVo.setValue(dept.getDeptId());
                    deptTreeVo.setLabel(dept.getName());
                    return deptTreeVo;
                }).collect(Collectors.toList());
    }

    @Override
    public boolean deleteDept(List<String> idList) {
        List<String> deptIdList=Lists.newArrayList();
        for(String deptId:idList){
            deptIdList.add(deptId);
            checkChildrenDept(deptIdList,deptId);
        }
        List<SysUser> userList = userService.list(Wrappers
                .<SysUser>query()
                .lambda()
                .select(SysUser::getUserId)
                .in(SysUser::getDeptId, deptIdList));
        if(CollUtil.isNotEmpty(userList)){
            throw new BaseException("部门下有用户,无法删除");
        }
        return baseMapper.deleteBatchIds(idList)>0;
    }

    private void checkChildrenDept(List<String> deptIdList,String deptId){
        List<SysDept> deptList = baseMapper.selectList(Wrappers.<SysDept>query().lambda().select(SysDept::getDeptId, SysDept::getParentId).eq(SysDept::getParentId, deptId));
        if(CollUtil.isNotEmpty(deptIdList)){
            for(SysDept dept:deptList){
                deptIdList.add(dept.getDeptId());
                checkChildrenDept(deptIdList,dept.getDeptId());
            }
        }
    }
    private void addDeptIdList(List<String> deptIdList, SysDept dept) {
        List<SysDept> children = dept.getChildren();
        if(CollectionUtil.isNotEmpty(children)){
            for(SysDept sysDept:children){
                deptIdList.add(sysDept.getDeptId());
                addDeptIdList(deptIdList,sysDept);
            }
        }
    }

    /**
     * 根据部门ID获取该部门及其下属部门树
     */
    private SysDept getDepartment(String deptId){
        List<SysDept> departments = baseMapper.selectList(Wrappers.<SysDept>query().select("dept_id", "name", "parent_id", "sort", "create_time"));
        Map<String, SysDept> deptMap = departments
                .stream()
                .collect(Collectors.toMap(SysDept::getDeptId, dept -> dept));
        for(SysDept dept:deptMap.values()){
            SysDept parent = deptMap.get(dept.getParentId());
            if(ObjectUtil.isNotNull(parent)){
                List<SysDept> children = parent.getChildren() == null ? Lists.newArrayList() : parent.getChildren();
                children.add(dept);
                parent.setChildren(children);
            }
        }
        return deptMap.get(deptId);
    }
}
